package com.wb.spring.boot.autoconfigure.register;

import com.wb.spring.boot.autoconfigure.annotation.ConditionalOnWbClientEnabled;
import com.wb.spring.boot.autoconfigure.WbProperties;
import com.wb.spring.boot.autoconfigure.WbRpcAutoConfiguration;
import com.wb.spring.boot.autoconfigure.http.WbHttpClientAutoConfiguration;
import com.wb.spring.boot.autoconfigure.load.Load;
import com.wb.spring.boot.autoconfigure.model.ServerInfo;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.env.Environment;
import org.springframework.data.redis.connection.RedisStandaloneConfiguration;
import org.springframework.data.redis.connection.jedis.JedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.listener.PatternTopic;
import org.springframework.data.redis.listener.RedisMessageListenerContainer;
import org.springframework.data.redis.listener.adapter.MessageListenerAdapter;
import org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.RedisSerializer;

import java.net.UnknownHostException;

/**
 * @author sw
 * @create 2023-03-03 9:43
 */

@Slf4j
@ConditionalOnWbClientEnabled
@ConditionalOnWbClientRegisterTypeRedis
@Configuration
@AutoConfigureAfter(value = {WbRpcAutoConfiguration.class, WbHttpClientAutoConfiguration.class})
public class WbRedisRegisterAutoConfiguration {


    /**
     * redis连接
     *
     * @param wbProperties
     * @return
     */
    @Bean
    public JedisConnectionFactory jedisConnectionFactory(WbProperties wbProperties) {
        WbProperties.RedisRegister redisRegister = wbProperties.getRedisRegister();
        RedisStandaloneConfiguration config = new RedisStandaloneConfiguration(redisRegister.getHost(), redisRegister.getPort());
        if (StringUtils.isNotBlank(redisRegister.getPassword())) {
            config.setPassword(redisRegister.getPassword());
        }

        return new JedisConnectionFactory(config);
    }

    /**
     * 注册器
     *
     * @param environment            环境变量
     * @param jedisConnectionFactory redis连接池
     * @param load                   负载均衡
     * @return
     * @throws UnknownHostException
     */
    @ConditionalOnBean(JedisConnectionFactory.class)
    @Bean
    public RedisRegister redisRegister(Environment environment, JedisConnectionFactory jedisConnectionFactory, Load load) throws UnknownHostException {
        // 创建JSON序列化工具
        GenericJackson2JsonRedisSerializer jsonRedisSerializer = new GenericJackson2JsonRedisSerializer();
        RedisTemplate redisTemplate = new RedisTemplate();
        // 设置key的序列化
        redisTemplate.setKeySerializer(RedisSerializer.string());
        redisTemplate.setHashKeySerializer(RedisSerializer.string());
        // 设置value的序列化
        redisTemplate.setValueSerializer(jsonRedisSerializer);
        redisTemplate.setHashValueSerializer(jsonRedisSerializer);
        redisTemplate.setConnectionFactory(jedisConnectionFactory);
        // 解析处本服务的基本信息
        ServerInfo serverInfo = new ServerInfo(environment);
        return new RedisRegister(redisTemplate, serverInfo, load);
    }

    /**
     * redis监听器
     *
     * @param redisRegister          redis注册中心
     * @param jedisConnectionFactory redis连接池
     * @return
     */
    @ConditionalOnBean(JedisConnectionFactory.class)
    @Bean
    RedisMessageListenerContainer container(RedisRegister redisRegister, JedisConnectionFactory jedisConnectionFactory) {
        MessageListenerAdapter redisSubscriber = new RedisSubscriber(redisRegister);
        RedisMessageListenerContainer container = new RedisMessageListenerContainer();
        container.setConnectionFactory(jedisConnectionFactory);
        container.addMessageListener(redisSubscriber, new PatternTopic("wbrpc"));
        return container;
    }


}
